home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 January - Disc 2 / Macworld (1999-01) (Disk 2).dmg / Shareware World / Comms & Internet / HTML and CSS modes / HTML and CSS Modes / cssMode.tcl next >
Text File  |  1998-05-16  |  15KB  |  436 lines

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  CSS mode - tools for editing CSS documents
  4.  # 
  5.  #  FILE: "cssMode.tcl"
  6.  #                                    created: 97-03-01 17.02.41 
  7.  #                                last update: 98-03-25 21.27.44 
  8.  #  Author: Johan Linde
  9.  #  E-mail: <jl@theophys.kth.se>
  10.  #     www: <http://bach.theophys.kth.se/~jl/Alpha.html>
  11.  #  
  12.  # Version: 1.1
  13.  # 
  14.  # Copyright 1997, 1998 by Johan Linde
  15.  #  
  16.  # This software may be used freely, and distributed freely, as long as the 
  17.  # receiver is not obligated in any way by receiving it.
  18.  #  
  19.  # If you make improvements to this file, please share them!
  20.  # 
  21.  # ###################################################################
  22.  ##
  23.  
  24. # Defining CSS mode
  25.  
  26. if {[alpha::package vsatisfies ${alpha::version} 7.1b1]} {
  27. alpha::mode CSS 1.1 cssMenu {*.css *.CSS} {
  28.     cssMenu electricBraces electricSemicolon electricReturn
  29. } {
  30.     addMenu cssMenu •150
  31. } uninstall {
  32.     set __dir [file dirname [procs::find cssMenu]]
  33.     catch {removeFile $__dir:cssMode.tcl}
  34.     if {[procs::find htmlMenu] == ""} {
  35.         catch {removeFile $__dir:hctsmsl.tcl}
  36.         catch {removeFile $__dir:hctsmslShared.tcl}
  37.         catch {removeFile $__dir:hctsmslMenu.tcl}
  38.         catch {removeFile "$HOME:Help:HTML Help"}
  39.         catch {removeFile "$HOME:Tcl:Completions:CSSCompletions.tcl"}
  40.     }
  41. } maintainer {
  42.     "Johan Linde" jl@theophys.kth.se <http://www.theophys.kth.se/~jl/Alpha.html>
  43. } help {file "HTML Help"}
  44. catch {unset CSSmodeVars(elecRBrace)}
  45. catch {unset CSSmodeVars(elecLBrace)}
  46. catch {unset CSSmodeVars(electricSemi)}
  47. } else {
  48. ;alpha::mode CSS 1.1 cssMenu {*.css *.CSS} cssMenu {
  49.     addMenu cssMenu •150
  50. } uninstall {
  51.     set __dir [file dirname [procs::find cssMenu]]
  52.     catch {removeFile $__dir:cssMode.tcl}
  53.     if {[procs::find htmlMenu] == ""} {
  54.         catch {removeFile $__dir:hctsmsl.tcl}
  55.         catch {removeFile $__dir:hctsmslShared.tcl}
  56.         catch {removeFile $__dir:hctsmslMenu.tcl}
  57.         catch {removeFile "$HOME:Help:HTML Help"}
  58.         catch {removeFile "$HOME:Tcl:Completions:CSSCompletions.tcl"}
  59.     }
  60. } maintainer {
  61.     "Johan Linde" jl@theophys.kth.se <http://www.theophys.kth.se/~jl/Alpha.html>
  62. } help {file "HTML Help"}
  63. # Electric left brace?
  64. newPref f elecRBrace 1 CSS
  65. # Electric right brace?
  66. newPref f elecLBrace 1 CSS
  67. # Electric semicolon?
  68. newPref f electricSemi 1 CSS
  69. }
  70.  
  71. proc cssMenu {} {}
  72.  
  73. newPref f wordWrap 0 CSS
  74. newPref v wordBreak {\w+} CSS
  75. newPref v wordBreakPreface {\W} CSS
  76. # Color of comments
  77. newPref v commentColor red CSS
  78. # Color of CSS keywords
  79. newPref v keywordColor blue CSS
  80. # Color of HTML elements
  81. newPref v htmlColor magenta CSS
  82. # Cmd-double-click on non text file link opens file?
  83. newPref f openNonTextFile 1 CSS
  84.  
  85. # Coloring
  86. proc cssColoring {} {
  87.     global CSSmodeVars
  88.     regModeKeywords -b {/*} {*/} -c $CSSmodeVars(commentColor) -k $CSSmodeVars(htmlColor) CSS [cssGetHtmlWords] 
  89.     regModeKeywords -a -k $CSSmodeVars(keywordColor) CSS {
  90.     font-family font-style font-variant font-weight font-size font 
  91.     color background-color background-image background-repeat background-attachment
  92.     background-position background word-spacing letter-spacing text-decoration
  93.     vertical-align text-transform text-align text-indent line-height
  94.     margin-top margin-right margin-bottom margin-left margin padding-top padding-right
  95.     padding-bottom padding-left padding border-top-width border-right-width
  96.     border-bottom-width border-left-width border-width border-color border-style
  97.     border-top border-right border-bottom border-left border width height float clear
  98.     display white-space list-style-type list-style-image list-style-position list-style
  99.     @import important
  100.     link visited active first-letter first-line}
  101. }
  102.  
  103. # Load other CSS mode files.
  104. foreach tmp {hctsmsl hctsmslShared hctsmslMenu} {
  105.     if {[info exists htmlModeIsLoaded] && ($tmp == "hctsmslMenu" || $tmp == "hctsmslShared")} {continue}
  106.     if {$tmp == "hctsmsl" && [info exists cssUnits]} {continue}
  107.     if { [catch {${tmp}.tcl}] } {
  108.         beep
  109.         alertnote "Loading of ${tmp}.tcl failed"
  110.         return
  111.     }
  112. }
  113.  
  114. proc cssHTMLelement {elem} {
  115.     insertText $elem
  116. }
  117.  
  118.  
  119. proc CSSDividingLine {} {
  120.     insertText "/*=============================================================================*/\r"
  121. }
  122. bind 'l' <C> CSSDividingLine CSS
  123.  
  124.  
  125. proc CSS::electricSemi {} {
  126.     insertText ";\r" [text::indentString [getPos]]
  127. }
  128.  
  129. proc CSS::parseFuncs {} {
  130.     set pos 0
  131.     set funcExpr {^[ \t]*([^\r\{]+)\{}
  132.     while {[set res [search -s -f 1 -r 1 -i 0 -n $funcExpr $pos]] != ""} {
  133.         if {[regexp $funcExpr [getText [car $res] [cadr $res]] dummy word]} {
  134.             lappend m [list $word [car $res]]
  135.         }
  136.         set pos [cadr $res]
  137.     }
  138.     return [join [lsort -ignore $m]]
  139. }
  140.  
  141. #===============================================================================
  142. # Key bindings
  143. #===============================================================================
  144.  
  145. # Define key bindings from html menu.
  146. proc cssBindingsFromMenu {me tmplist} {
  147.     global htmlMenuKey html${me}Sub
  148.     upvar $tmplist tmp
  149.     foreach it [set html${me}Sub] {
  150.         if {[llength $it] > 2} {
  151.             set elem [lindex $it 2]            
  152.              if {[info exists htmlMenuKey(${me}/[lindex $it 1])]} {
  153.                 set key $htmlMenuKey(${me}/[lindex $it 1])
  154.             } else {
  155.                 set key [lindex $it 0]
  156.             }
  157.             cssBindOneKey $key $elem "" tmp
  158.         }
  159.     }
  160. }
  161.  
  162. proc cssBindOneKey {key elem {un ""} {tmplist ""}} {
  163.     set key1 [keys::toBind $key]
  164.     # Work around bug in keys::toBind
  165.     if {[regexp "/b" $key]} {set key1 [lreplace $key1 0 0 0x24]}
  166.     if {$key1 == ""} {return}
  167.     eval ${un}bind $key1 [list "cssHTMLelement $elem"] CSS
  168.     if {$tmplist != ""} {
  169.         upvar $tmplist tmp
  170.         append tmp [concat ${un}bind $key1 [list "cssHTMLelement $elem"] CSS] \r
  171.     }
  172. }
  173.  
  174. # Redefine key bindings when changed in HTML menu.
  175. proc cssReBindKey {meny keyItems} {
  176.     global html${meny}Sub
  177.     set items [set html${meny}Sub]
  178.     foreach it $keyItems {
  179.         set it0 [lindex $it 0]
  180.         foreach it1 $items {
  181.             if {[lindex $it1 1] == $it0} {
  182.                 set elem [lindex $it1 2]
  183.                 break
  184.             }
  185.         }
  186.         # Skip those which aren't html elements
  187.         if {[llength $it1] < 3} {continue}
  188.         cssBindOneKey [lindex $it 1] $elem un
  189.         cssBindOneKey [lindex $it 2] $elem
  190.     }
  191. }
  192.  
  193. proc cssMenuKeys {} {
  194.     global htmlMenuKey
  195.     set rebuildCSS 0
  196.     set somethingModified 0
  197.     htmlReadMenuKeys
  198.     htmlSetKeysInMenu CSS
  199.     if {$somethingModified} {htmlWriteMenuKeys}
  200.     catch {unset htmlMenuKey}
  201.     if {$rebuildCSS} {cssRebuildMenu}
  202. }
  203.  
  204. #===============================================================================
  205. # Menu handling
  206. #===============================================================================
  207.  
  208. set htmlCSSSub [concat [lrange $htmlStyleSub 3 end] {"(-" {"<O<U/S" "Reload in Browser"} {"" "Colors…"} {"" "Key Bindings…"} {"" "Preferences…"}}]
  209.  
  210. proc cssBuildMenu {} {
  211.     global cssMenu htmlMenuKey
  212.     if {[catch {htmlReadCache "CSS menu cache" css}]} {
  213.         htmlReadMenuKeys
  214.         set me [htmlBuildOneMenu CSS]
  215.         menu -M CSS -p cssMenuItem -m -n $cssMenu $me
  216.         set h {menu -M CSS -p cssMenuItem -m -n $cssMenu}
  217.         lappend h $me
  218.         htmlSaveCache "CSS menu cache" $h css
  219.     }
  220.     catch {unset htmlMenuKey}
  221. }
  222.  
  223. proc cssRebuildMenu {} {
  224.     htmlDeleteCache "CSS menu cache"
  225.     cssBuildMenu
  226. }
  227.  
  228. proc cssMenuItem {menu item} {
  229.     switch $item {
  230.         "Reload in Browser" {cssReloadinBrowser}
  231.         Colors {htmlColors}
  232.         "Key Bindings" {cssMenuKeys}
  233.         "Preferences" {CSSmodifyFlags}
  234.         Import {cssDialog @import}
  235.         Display {cssDialog Display}
  236.         default {cssDialog [join [string tolower $item] -]}
  237.     }
  238. }
  239.  
  240. #===============================================================================
  241. # Cmd-double-click
  242. #===============================================================================
  243.  
  244. proc CSS::DblClick {from to} {
  245.     HTML::DblClick $from $to
  246. }
  247.  
  248. #===============================================================================
  249. # Reload in Browser
  250. #===============================================================================
  251.  
  252. proc cssReloadinBrowser {} {
  253.     global browserSig HTMLmodeVars
  254.     if {$browserSig != "MOSS" && $browserSig != "MSIE"} {
  255.         beep; message "Works only with Netscape and MSIE."; return
  256.     }
  257.     # returns window ids
  258.     if {![regexp {\[([0-9]+)} [AEBuild -r '$browserSig' WWW! LSTW] dum winnum]} {beep; message "No browser window."; return}
  259.     if {[winDirty]} {
  260.         if {[set ask [askyesno -c "Save '[lindex [winNames] 0]'?"]] == "yes"} {
  261.             save
  262.         } elseif {$ask == "cancel"} {
  263.             return
  264.         }
  265.     }
  266.     # returns window info
  267.     regexp {\[([^ ]+)} [AEBuild -r '$browserSig' WWW! WNFO ---- $winnum] dum winurl
  268.     set winurl [string trim $winurl "“”,"]
  269.     if {$winurl == "'TEXT'()"} {beep; message "Empty browser window."; return}
  270.     # reloads window
  271.     set flgs ""
  272.     if {$browserSig == "MSIE"} {set flgs "FLGS 1"}
  273.     eval AEBuild '$browserSig' WWW! OURL ---- "“$winurl”" $flgs
  274.     if {![info exists HTMLmodeVars(browseInForeground)] || $HTMLmodeVars(browseInForeground)} {switchTo '$browserSig'}
  275. }
  276.  
  277.  
  278. #===============================================================================
  279. # Preferences
  280. #===============================================================================
  281.  
  282. if {![alpha::package vsatisfies ${alpha::version} 7.1b1]} {
  283. proc CSSmodifyFlags {} {
  284.     global CSSmodeVars modifiedModeVars colorInds
  285.     set colors {none blue cyan green magenta red white yellow}
  286.     foreach c [lsort [array names colorInds]] {
  287.         if {[regexp {color} $c]} {lappend colors $c}
  288.     }
  289.     set box "-t {CSS mode Preferences} 100 10 450 30 \
  290.     -c {Electric left braces} $CSSmodeVars(elecLBrace) 10 35 450 50 \
  291.     -c {Electric right braces} $CSSmodeVars(elecRBrace) 10 55 450 70 \
  292.     -c {Electric semicolon} $CSSmodeVars(electricSemi) 10 75 450 90 \
  293.     -c {Cmd-double-clicking on non-text file link opens file} $CSSmodeVars(openNonTextFile) 10 95 450 110 \
  294.     -t {Color of keywords:} 10 115 150 130 \
  295.     -m [list [concat $CSSmodeVars(keywordColor) $colors]] 160 115 310 135 \
  296.     -t {Color of comments:} 10 140 150 155 \
  297.     -m [list [concat $CSSmodeVars(commentColor) $colors]] 160 140 310 155 \
  298.     -t {Color of HTML:} 10 165 150 180 \
  299.     -m [list [concat $CSSmodeVars(htmlColor) $colors]] 160 165 310 180 \
  300.     -t wordBreak: 10 190 150 205 \
  301.     -e [list $CSSmodeVars(wordBreak)] 155 190 450 205 \
  302.     -t wordBreakPreface: 10 215 150 230 \
  303.     -e [list $CSSmodeVars(wordBreakPreface)] 155 215 450 230"
  304.     set values [eval [concat dialog -w 460 -h 275 -b OK 20 245 85 265 -b Cancel 110 245 175 265 $box]]
  305.     if {[lindex $values 1]} {return}
  306.     set i 1
  307.     foreach flag {elecLBrace elecRBrace electricSemi openNonTextFile keywordColor
  308.     commentColor htmlColor wordBreak wordBreakPreface} {
  309.         global $flag
  310.         incr i
  311.         set val [lindex $values $i]
  312.         if {$CSSmodeVars($flag) != $val} {
  313.             set $flag $val
  314.             set CSSmodeVars($flag) $val
  315.             lappend modifiedModeVars [list $flag CSSmodeVars]
  316.             if {[string match "*Color" $flag]} {cssColoring}
  317.         }
  318.     }
  319. }
  320. } else {
  321. proc CSSmodifyFlags {} {
  322.     global CSSmodeVars modifiedModeVars colorInds
  323.     set colors {none blue cyan green magenta red white yellow}
  324.     foreach c [lsort [array names colorInds]] {
  325.         if {[regexp {color} $c]} {lappend colors $c}
  326.     }
  327.     set box "-t {CSS mode Preferences} 100 10 450 30 \
  328.     -c {Cmd-double-clicking on non-text file link opens file} $CSSmodeVars(openNonTextFile) 10 35 450 50 \
  329.     -t {Color of keywords:} 10 55 150 70 \
  330.     -m [list [concat $CSSmodeVars(keywordColor) $colors]] 160 55 310 75 \
  331.     -t {Color of comments:} 10 80 150 95 \
  332.     -m [list [concat $CSSmodeVars(commentColor) $colors]] 160 80 310 100 \
  333.     -t {Color of HTML:} 10 105 150 120 \
  334.     -m [list [concat $CSSmodeVars(htmlColor) $colors]] 160 105 310 120 \
  335.     -t wordBreak: 10 130 150 145 \
  336.     -e [list $CSSmodeVars(wordBreak)] 155 130 450 145 \
  337.     -t wordBreakPreface: 10 155 150 170 \
  338.     -e [list $CSSmodeVars(wordBreakPreface)] 155 155 450 170"
  339.     set values [eval [concat dialog -w 460 -h 215 -b OK 20 185 85 205 -b Cancel 110 185 175 205 $box]]
  340.     if {[lindex $values 1]} {return}
  341.     set i 1
  342.     foreach flag {openNonTextFile keywordColor
  343.     commentColor htmlColor wordBreak wordBreakPreface} {
  344.         global $flag
  345.         incr i
  346.         set val [lindex $values $i]
  347.         if {$CSSmodeVars($flag) != $val} {
  348.             set $flag $val
  349.             set CSSmodeVars($flag) $val
  350.             lappend modifiedModeVars [list $flag CSSmodeVars]
  351.             if {[string match "*Color" $flag]} {cssColoring}
  352.         }
  353.     }
  354. }
  355. }
  356. #===============================================================================
  357. # Initialization
  358. #===============================================================================
  359.  
  360. set cssVersion 2.1
  361.  
  362. # Define key bindings.
  363. if {[catch {htmlReadCache "CSS keybindings cache" css}]} {
  364.     htmlReadMenuKeys
  365.     message "Defining key bindings…"
  366.     foreach tmp [lrange $htmlSubMenus $htmlStartElements end] {
  367.         cssBindingsFromMenu [lindex $tmp 0] tmplist
  368.     }
  369.     if {[info exists htmlModeIsLoaded]} {
  370.         foreach tmp [array names htmlElemKeyBinding] {
  371.             cssBindOneKey $htmlElemKeyBinding($tmp) $tmp "" tmplist
  372.         }
  373.     } elseif {[file exists $PREFS:HTMLadditions.tcl]} {
  374.         set tmpcid [scancontext create]
  375.         scanmatch $tmpcid {htmlElemKeyBinding} {
  376.             cssBindOneKey [lindex [lindex $matchInfo(line) 1] 2] [lindex $matchInfo(line) 0] "" tmplist
  377.         }
  378.         if {![catch {open $PREFS:HTMLadditions.tcl} tmpfid]} {
  379.             scanfile $tmpcid $tmpfid
  380.             close $tmpfid
  381.         }
  382.         scancontext delete $tmpcid
  383.         catch {unset tmpcid tmpfid}
  384.     }
  385.     htmlSaveCache "CSS keybindings cache" $tmplist css
  386.     unset tmplist
  387.     catch {unset htmlMenuKey}
  388. } else {
  389.     message "Reading key bindings…"
  390. }
  391.  
  392. if {![info exists htmlModeIsLoaded]} {
  393.     set cssHtmlWords {A ABBR ACRONYM ADDRESS APPLET AREA B BASE 
  394.         BASEFONT BDO BGSOUND BIG BLINK BLOCKQUOTE BODY BR BUTTON CAPTION 
  395.         CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM EMBED 
  396.         FIELDSET FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I 
  397.         IFRAME ILAYER IMG INPUT INS ISINDEX KBD KEYGEN LABEL LAYER LEGEND 
  398.         LI LINK MAP MARQUEE MENU META MULTICOL NOBR NOEMBED NOFRAMES 
  399.         NOLAYER NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PRE Q SAMP 
  400.         SCRIPT SELECT SERVER SMALL SPACER SPAN STRIKE STRONG STYLE SUB SUP TABLE 
  401.         TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR WBR}
  402.     if {[file exists $PREFS:HTMLadditions.tcl]} {
  403.         set tmpcid [scancontext create]
  404.         scanmatch $tmpcid {htmlElemKeyBinding} {
  405.             lappend cssHtmlWords [lindex $matchInfo(line) 0]
  406.         }
  407.         if {![catch {open $PREFS:HTMLadditions.tcl} tmpfid]} {
  408.             scanfile $tmpcid $tmpfid
  409.             close $tmpfid
  410.         }
  411.         scancontext delete $tmpcid
  412.         catch {unset tmpcid tmpfid}
  413.     }
  414. }
  415.  
  416. cssColoring
  417. cssBuildMenu
  418. unset tmp
  419. rename cssBindingsFromMenu ""
  420.  
  421.  
  422. set commentCharacters(CSS:General) "/*"
  423. set commentCharacters(CSS:Paragraph) [list "/* " " */" " * "]
  424. set commentCharacters(CSS:Box) [list "/*" 2 "*/" 2 "*" 3]
  425.  
  426.  
  427. if {[info exists htmlModeIsLoaded] && $htmlVersion != $cssVersion} {
  428.     alertnote "Warning: The versions of HTML mode and CSS mode may not be compatible.\
  429.         Always install new versions of HTML mode and CSS mode simultaneously."
  430. }
  431.  
  432. set cssModeIsLoaded 1
  433.  
  434. message "CSS initialization complete."
  435.  
  436.